package org.ting.j20250110_gobang.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.ting.j20250110_gobang.game.*;
import org.ting.j20250110_gobang.model.User;
import org.ting.j20250110_gobang.service.UserService;

import java.io.IOException;

@Component
public class GameWebSocket extends TextWebSocketHandler {
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RoomManager roomManager;
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private UserService userService;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        GameReadyResponse response = new GameReadyResponse();
        //1.获取用户信息
        User user = (User)session.getAttributes().get("user");
        if(user == null) {
            System.out.println("用户未登录");
            response.setMessage("no_login");
            response.setOk(true);
            response.setErrMsg("用户未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }


        Room room = null;
        try {
            //2. 检测用户是否进入房间
            room = roomManager.getRoomByUserId(user.getUserId());
            if(room == null) {
                response.setOk(false);
                response.setErrMsg("用户未成功进入房间");
                System.out.println("用户未成功进入房间");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                return;
            }
        }catch (NullPointerException e) {
            //游戏房间已经销毁
            response.setOk(false);
            response.setErrMsg("游戏房间已经销毁");
            System.out.println("游戏房间已经销毁");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }



        //3. 判断玩家是否在别处登录
        if(onlineUserManager.getFromHall(user.getUserId()) != null
        || onlineUserManager.getFromRoom(user.getUserId()) != null) {

            response.setMessage("repeat_login");
            response.setOk(true);
            response.setErrMsg("用户已在别处登录");
            System.out.println("用户已在别处登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }

        //4.设置玩家上线，维护游戏房间内在线状态
        onlineUserManager.enterGameRoom(user.getUserId(), session);

        synchronized (room) {
            //5. 把玩家加入游戏房间
            if(room.getUser1() == null) {
                //对手还未进入房间
                room.setUser1(user);
                System.out.println("玩家 " + user.getUsername() + "进入游戏房间");
                return ;
            }
            if(room.getUser2() == null) {
                //对手已经进入房间
                room.setUser2(user);
                System.out.println("玩家 " + user.getUsername() + "进入游戏房间");
                //随机设置先手玩家
                if(System.currentTimeMillis() % 2 == 0) {
                    room.setBlackUser(room.getUser1().getUserId());
                }else{
                    room.setBlackUser(room.getUser2().getUserId());
                }
                //通知玩家1
                noticeGameReady(room, room.getUser1(), room.getUser2());
                //通知玩家2
                noticeGameReady(room, room.getUser2(), room.getUser1());
            }
        }
    }
    private void noticeGameReady(Room room, User user1, User user2) throws IOException {
        GameReadyResponse response = new GameReadyResponse();
        response.setMessage("gameReady");
        response.setOk(true);
        response.setRoomId(room.getRoomId());
        response.setUserId1(user1.getUserId());
        response.setUserId2(user2.getUserId());
        response.setBlack(user1.getUserId() == room.getBlackUser());

        onlineUserManager.getFromRoom(user1.getUserId())
                .sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //1. 获取用户信息
        User user = (User)session.getAttributes().get("user");
        //2. 获取请求信息
        GameRequest request = objectMapper.readValue(message.getPayload(),GameRequest.class);
        //3. 调用游戏房间中的putChess方法实现落子
        Room room = roomManager.getRoomByUserId(user.getUserId());
        room.putChess(request);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        try {
            User user = (User)session.getAttributes().get("user");
            WebSocketSession exitSession = onlineUserManager.getFromRoom(user.getUserId());
            if(exitSession.equals(session)) {
                onlineUserManager.exitGameRoom(user.getUserId());
                System.out.println("连接异常断开，" + user.getUsername() + "退出游戏房间");
                //通知对手获胜
                noticeWinner(user);
            }
        }catch (NullPointerException e) {
            //出现空指针异常说明用户未登录
            //e.printStackTrace();
            System.out.println("GameWebSocket.handleTransportError 用户未登录");
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            User user = (User)session.getAttributes().get("user");
            WebSocketSession exitSession = onlineUserManager.getFromRoom(user.getUserId());
            if(exitSession.equals(session)) {
                onlineUserManager.exitGameRoom(user.getUserId());
                onlineUserManager.exitGameRoom(user.getUserId());
                System.out.println("连接正常断开，" + user.getUsername() + "退出游戏房间");
                //通知对手获胜
                noticeWinner(user);
            }
        }catch (NullPointerException e) {
            //出现空指针异常说明用户未登录
            //e.printStackTrace();
            System.out.println("GameWebSocket.afterConnectionClosed 用户未登录");
        }
    }

    private void noticeWinner(User user) throws IOException {
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if(room == null) {
            //房间已经被释放，游戏正常结束
            return;
        }
        User winner = user == room.getUser1() ? room.getUser2() : room.getUser1();
        WebSocketSession session = onlineUserManager.getFromRoom(winner.getUserId());
        if(session == null) {
            //说明对手也掉线了
            return;
        }
        GameResponse response = new GameResponse();
        response.setMessage("putChess");
        response.setUserId(user.getUserId());
        response.setRow(-1);
        response.setCol(-1);
        response.setWinnerId(winner.getUserId());
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));

        System.out.println("更新玩家信息");
        userService.userWin(winner.getUserId());
        userService.userLose(user.getUserId());

        //释放房间
        roomManager.remove(room.getRoomId(), room.getUser1().getUserId(), room.getUser2().getUserId());
    }
}
